package server;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response.Status;
import javax.xml.bind.DatatypeConverter;

import persistence.DAOException;
import persistence.LoginManager;
import persistence.LoginManagerHSQLDB;
import utilities.Logger;

import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerRequestFilter;


/**
 * This class handles the basic-auth for the REST-service.
 * @author Felix
 */
public class RestAuth implements ContainerRequestFilter {
	
	private static Logger log = Logger.getLogger(RestAuth.class);
	
	/**
	 * Modified jersey HTTP Basic Auth filter
	 * @author Deisss (LGPLv3), Felix
	 */
    @Override
    public ContainerRequest filter(ContainerRequest containerRequest) throws WebApplicationException {

        //Get the authentification passed in HTTP headers parameters
        String auth = containerRequest.getHeaderValue("authorization");
 
        //If the user does not have the right (does not provide any HTTP Basic Auth)
        if(auth == null){
        	log.w("Auth was null");
            throw new WebApplicationException(Status.UNAUTHORIZED);
        }
 
        //lap : loginAndPassword
        String[] lap = b64decodeAuth(auth);
 
        //If login or password fail
        if(lap == null || lap.length != 2){
            throw new WebApplicationException(Status.UNAUTHORIZED);
        }
 
        LoginManager lm;
		try {
			lm = LoginManagerHSQLDB.getInstance();
	
        
        if (lm.logIn(lap[0], lap[1])) {
        	//TODO : Add User-Parameter to request?
        	log.d("Auth successful.");
            return containerRequest;
        } else {
        	log.d("Wrong username / password.");
            throw new WebApplicationException(Status.UNAUTHORIZED);
        }
		} catch (DAOException e) {
			log.e("DAOException: " + e.getMessage());
            throw new WebApplicationException(404);
		}
    }
    
    /**
     * Decode the basic auth and convert it to array login/password
     * @author Deisss (LGPLv3)
     * @param auth The string encoded authentification
     * @return The login (case 0), the password (case 1)
     */
    private String[] b64decodeAuth(String auth) {
    	//Replacing "Basic THE_BASE_64" to "THE_BASE_64" directly
        auth = auth.replaceFirst("[B|b]asic ", "");
 
        //Decode the Base64 into byte[]
        byte[] decodedBytes = DatatypeConverter.parseBase64Binary(auth);
 
        //If the decode fails in any case
        if(decodedBytes == null || decodedBytes.length == 0){
            return null;
        }
 
        //Now we can convert the byte[] into a splitted array :
        //  - the first one is login,
        //  - the second one password
        return new String(decodedBytes).split(":", 2);
    }
}